#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <math.h>

#include "bsp_key.h"

#include "los_task.h"

//定义ADC初始化的结构体
static DevIo m_adcKey = {
    .isr = {.gpio = INVALID_GPIO},
    .rst = {.gpio = INVALID_GPIO},
    .ctrl1 = {  
        .gpio = GPIO0_PC5, 
        .func = MUX_FUNC1, 
        .type = PULL_NONE, 
        .drv = DRIVE_KEEP, 
        .dir = LZGPIO_DIR_IN,
        .val = LZGPIO_LEVEL_KEEP
    },
    .ctrl2 = {.gpio = INVALID_GPIO}
};

int key_adc_dev_init()
{
    int ret = 0;
    //地址 用于配置芯片的杂项功能（包括ADC电压选择）
    uint32_t *pGrfSocCon29 = (uint32_t *)(0x41050000U + 0x274U);    
    uint32_t ulValue;

    ret = DevIoInit(m_adcKey);
    if(ret != LZ_HARDWARE_SUCCESS)
    {
        printf("%s, %s, %d: ADC Key IO Init fail\n", __FILE__, __func__, __LINE__);
        return -1;
    }
    ret = LzSaradcInit();
    if(ret != LZ_HARDWARE_SUCCESS) {
        printf("%s, %s, %d: ADC Init fail\n", __FILE__, __func__, __LINE__);
        return -2;
    }

    //设置saradc电压信号，选择AVDD
    ulValue = *pGrfSocCon29;
    /**
     * Bit 4：控制SARADC（逐次逼近型ADC）的参考电压源选择：
     * 0：选择内部参考电压（通常1.8V）
     * 1：选择AVDD（模拟电源电压，通常3.3V）
    */
    ulValue &= ~(0x1 << 4); // 清除Bit4（保留其他位）
    /**
     * Bit 20（Bit 4的写使能位）：
     * 需要同时置位该位才能使Bit 4的修改生效（Rockchip的寄存器保护机制）。
    */
    ulValue |= ((0x1 << 4) << 16);  // 设置Bit20（写使能）和Bit4（选择AVDD）
    *pGrfSocCon29 = ulValue;

    return 0;
}

static float adc_get_voltage()
{
    unsigned int ret = LZ_HARDWARE_SUCCESS;
    uint32_t data;
    // uint32_t sum = 0;
    // int i = 0;
    
    // TODO 均值滤波 
    ret = LzSaradcReadValue(ADC_CHANNEL, &data);
    if(ret != LZ_HARDWARE_SUCCESS)
    {
        printf("%s, %s, %d: ADC Read Fail\n", __FILE__, __func__, __LINE__);
        return 0.0;
    }

    return (float)(data * 3.3 / 1024.0);
}

int key_scan(int mode)
{
    static int flag = 0;
    float voltage = 0;
    
    int key = NOKEY_PRES;

    // LOS_Msleep(20);    //20毫秒
    voltage = adc_get_voltage();
    // printf("---------->adc_key v: %f", voltage);

    if(0.0 <= voltage && voltage <=0.1)     //7mV  实际 0.00V ~ 0.01V
    {
        key = KEY1_PRES;
    }
    else if(0.5<=voltage && voltage<=0.6) // KEY2 -- 0.55V  实际0.5V ~ 0.6V
    {
        key = KEY2_PRES;
    }
    else if(1.0<=voltage && voltage<=1.2) // KEY3 -- 1.05V  实际1.0V ~ 1.2V
    {
        key = KEY3_PRES;
    }
    else if(1.6<=voltage && voltage<=1.8) // KEY4 -- 1.65V 实际1.6V ~ 1.8V
    {
        key = KEY4_PRES;
    }

    if(key == NOKEY_PRES)
        flag = 0;

    if(mode == 0)   //不支持长按
    {
        if(flag == 0 && key != NOKEY_PRES)
        {
            flag = 1;   //之前按键一直按着没松
            return key;
        }

        return NOKEY_PRES;
    }

    return key;
}

static float mean_filter(const uint16_t* data, uint8_t len)
{
    uint32_t sum = 0;
    for(uint8_t i = 0; i < len; i++)
        sum += data[i];
    return sum / (float)len;
}

